﻿using FunArts.EasyDevOps.Shared.Models.SshClient;
using FunArts.EasyDevOps.Shared.Models.SshClient.Command;
using FunArts.EasyDevOps.Shared.Models.SshClient.CommandResult;
using FunArts.EasyDevOps.Shared.Models.SshWebSocket.Enums;
using FunArts.EasyDevOps.Shared.Models.SshWebSocket.Request;
using FunArts.EasyDevOps.Shared.Models.SshWebSocket.Response;
using FunArts.EasyDevOps.Shared.Utils;
using Renci.SshNet;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices.JavaScript;
using System.Text;
using System.Text.Json;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using static System.Net.WebRequestMethods;

namespace FunArts.EasyDevOps.Rcl.Service.Impl
{
    /// <summary>
    /// 服务端平台ssh连接实现
    /// </summary>
    public class SshClientService: ISshClientService
    {
        public SshClientConnectInfo SshClientConnectInfo { get; set; }

        public bool IsConnected => throw new NotImplementedException();

        private readonly SshWebSocketClient _webSocketClient;

        public SshClientService(string webSocketUrl)
        {
            _webSocketClient = new SshWebSocketClient(webSocketUrl);
        }

        public bool Connect(out string errMsg)
        {
            ConnectRequest request = new ConnectRequest()
            {
                ConnectInfo = SshClientConnectInfo,
            };
            var response = _webSocketClient.SendRequestAsync(SshWebSocketRequestTypeEnum.Connect, request).Result;
            var result = JsonSerializer.Deserialize<SshWebSocketResponse<ConnectResponse>>(response);

            if (result.Success)
            {
                SshClientConnectInfo=result.SshResponse.ConnectInfo;
                errMsg = string.Empty;
                return true;
            }
            else
            {
                errMsg = result.Error;
                return false;
            }
        }

        public void Disconnect()
        {
            // WebSocket 不需要显式断开连接
        }

        public LinuxCommandResultBase ExecuteCommand<T>(T command) where T : ILinuxCommand
        {
            ExecuteCommandRequest request = new ExecuteCommandRequest()
            {
                Command= command.BuildCommand(SshClientConnectInfo.SystemVersionType)
            };
            var response = _webSocketClient.SendRequestAsync(SshWebSocketRequestTypeEnum.ExecuteCommand, request).Result;
            var result = JsonSerializer.Deserialize<SshWebSocketResponse<ExecuteCommandResponse>>(response);

            return new LinuxCommandResultBase
            {
                Output = result.SshResponse.Output,
                ExitStatus = result.SshResponse.ExitStatus,
                Error = result.SshResponse.Error
            };
        }

        public void UploadFile(byte[] fileData, string remoteFilePath)
        {
            UploadFileRequest request = new UploadFileRequest()
            {
                FileData = fileData,
                RemoteFilePath = remoteFilePath
            };
            var response = _webSocketClient.SendRequestAsync(SshWebSocketRequestTypeEnum.UploadFile, request).Result;
            var result = JsonSerializer.Deserialize<SshWebSocketResponse<object>>(response);

            if (!result.Success)
            {
                throw new Exception(result.Error);
            }
        }

        public byte[] DownloadFile(string remoteFilePath)
        {
            DownloadFileRequest request = new DownloadFileRequest()
            {
                RemoteFilePath = remoteFilePath
            };
            var response = _webSocketClient.SendRequestAsync(SshWebSocketRequestTypeEnum.DownloadFile, request).Result;
            var result = JsonSerializer.Deserialize<SshWebSocketResponse<DownloadFileResponse>>(response);

            if (result.SshResponse.FileData != null)
            {
                return result.SshResponse.FileData;
            }
            else
            {
                throw new Exception(result.Error);
            }
        }

        /// <summary>
        /// 查找文件
        /// </summary>
        /// <param name="directory"></param>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public LinuxCommandResultBase FindFile(string directory, string fileName)
        {
            ILinuxCommand linuxCommand=new FindCommand(directory, fileName);
            return ExecuteCommand(linuxCommand);
        }
        /// <summary>
        /// 加载目录
        /// </summary>
        /// <param name="node"></param>
        public async Task LoadDirectoryTree(DirectoryNode node)
        {
            node = await _webSocketClient.LoadDirectoryTree(node);
        }

        public LinuxCommandResultBase ExecuteCommand(Func<ILinuxCommand> createCommandFunc)
        {
            return ExecuteCommand(createCommandFunc());
        }
    }
}
